#include "qlanguagemanagerview.h"

#include "qaddlanguagedialog.h"


#include "../../libs/sharedlib/qprojectcore.h"
#include "../../libs/sharedlib/qprojecthost.h"
#include "../../libs/corelib/styledbar.h"
#include "../../libs/corelib/qactiontoolbar.h"
#include "../../libs/corelib/qsoftcore.h"
#include "../../libs/sharedlib/qlanguagemanager.h"
#include "../../libs/sharedLib/qnamevalidator.h"
#include "../../libs/coreLib/qundocommand/qabstractundocommand.h"
#include "../../libs/coreLib/qundocommand/qcommandobject.h"
#include "../../libs/sharedLib/qcommonstruct.h"


#include <QVBoxLayout>
#include <QHeaderView>
#include <QAction>
#include <QLabel>
#include <QPainter>
#include <QApplication>
#include <QSpinBox>
#include <QKeyEvent>

QWidget *QLanguageDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/*option*/, const QModelIndex &index) const
{
    QWidget *ret=NULL;
    if(index.column()==1)
    {
        SHAREDLIB::QNameEdit *edit=new SHAREDLIB::QNameEdit("(.*)",parent);
        edit->setValue(index.data().toString());
        SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();
        SHAREDLIB::QLanguageManager *manager=core->languageManager();
        QStringList list;
        for(int i=0;i<manager->languageCount();i++)
        {
            list.append(manager->getLanguage(i)->property("languageName").toString());
        }
        list.removeAll(index.data().toString());
        edit->setIntermediateList(list);
        edit->setFrame(false);
        ret=edit;
    }
    else if(index.column()==2)
    {
        ret=new QLineEdit(parent);
        ((QLineEdit*)ret)->setFrame(false);
    }
    if(ret!=NULL)
    {
        ret->setProperty("no-ManhattanStyle",true);
    }
    return ret;
}

void QLanguageDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
{
    editor->setGeometry(option.rect.adjusted(0,0,0,-1));
}

QSize QLanguageDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QSize size=QItemDelegate::sizeHint(option,index);
    size.setHeight(21);
    return size;
}

void QLanguageDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QString str=model->index(index.row(),1).data().toString();
    SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();
    QObject *obj=core->languageManager()->getLanguage(str);
    QItemDelegate::setModelData(editor,model,index);
    QModelIndex m=model->index(index.row(),index.column());
    if(obj!=NULL)
    {
        if(index.column()==1)
        {
            if(obj->property("languageName").toString()!=m.data().toString())
            {
                emit m_view->need_make_page_position();
                QMap<QString,QVariant>   param;
                param.insert("old_name",obj->property("languageName"));
                param.insert("new_name",m.data());
                tagPagePositionInfo info=m_view->m_page_position.value<tagPagePositionInfo>();
                info.m_data.insert("QLanguageManagerView::select",index.row());
                QVariant v;
                v.setValue<tagPagePositionInfo>(info);
                param.insert("page_position",v);
                CORELIB::QAbstractUndoCommand *cmd=new CORELIB::QAbstractUndoCommand(param);
                connect(cmd->object(),SIGNAL(redo()),m_view,SLOT(cammand_rename()));
                connect(cmd->object(),SIGNAL(undo()),m_view,SLOT(cammand_rename()));
                CORELIB::QSoftCore::getCore()->get_undo_stack()->push(cmd);
            }
        }
        else if(index.column()==2)
        {
            if(obj->property("explanation").toString()!=m.data().toString())
            {
                emit m_view->need_make_page_position();
                QMap<QString,QVariant>   param;
                param.insert("old_value",obj->property("explanation"));
                param.insert("new_value",m.data());
                param.insert("language",obj->property("languageName"));
                tagPagePositionInfo info=m_view->m_page_position.value<tagPagePositionInfo>();
                info.m_data.insert("QLanguageManagerView::select",index.row());
                QVariant v;
                v.setValue<tagPagePositionInfo>(info);
                param.insert("page_position",v);
                CORELIB::QAbstractUndoCommand *cmd=new CORELIB::QAbstractUndoCommand(param);
                connect(cmd->object(),SIGNAL(redo()),m_view,SLOT(cammand_property()));
                connect(cmd->object(),SIGNAL(undo()),m_view,SLOT(cammand_property()));
                CORELIB::QSoftCore::getCore()->get_undo_stack()->push(cmd);
            }
        }
    }
}

void QLanguageDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItemV3 opt=option;

    QColor c=QColor(255,255,191);

    if(opt.features & QStyleOptionViewItemV2::Alternate)
    {
        c=c.lighter(112);
    }
    painter->fillRect(option.rect,c);
    opt.state &=~ QStyle::State_HasFocus;
    QItemDelegate::paint(painter,opt,index);
    opt.palette.setCurrentColorGroup(QPalette::Active);
    QColor color=static_cast<QRgb>(qApp->style()->styleHint(QStyle::SH_Table_GridLineColor,&opt));
    painter->setPen(color);

    int right=option.direction==Qt::LeftToRight?option.rect.right():option.rect.left();
    painter->drawLine(right,option.rect.y(),right,option.rect.bottom());

    painter->drawLine(option.rect.left(),option.rect.bottom(),option.rect.right(),option.rect.bottom());
}

QLanguageManagerView::QLanguageManagerView(QWidget *parent) :
    QWidget(parent),
    m_languageList(new QTreeWidget),
    m_styledBar(new CORELIB::StyledBar)
{

    QVBoxLayout *l=new QVBoxLayout;
    l->setMargin(0);
    l->setSpacing(0);
    l->addWidget(m_styledBar);
    l->addWidget(m_languageList);

    this->setLayout(l);

    m_languageList->setFrameStyle(QFrame::NoFrame);

    QStringList list;
    list<<tr("No.")<<tr("Language")<<tr("Explanation");
    m_languageList->setHeaderLabels(list);
    m_languageList->setAlternatingRowColors(true);
    m_languageList->setEditTriggers(QAbstractItemView::EditKeyPressed);
    m_languageList->setRootIsDecorated(false);
    m_languageList->header()->setMovable(false);
    m_languageList->setItemDelegate(new QLanguageDelegate(this));
    m_languageList->setColumnWidth(0,100);
    m_languageList->installEventFilter(this);

    CORELIB::QActionToolBar* toolbar=new CORELIB::QActionToolBar(Qt::AlignRight);
    l=new QVBoxLayout;
    l->setMargin(0);
    l->setSpacing(5);
    l->addWidget(toolbar);
    m_styledBar->setLayout(l);

    CORELIB::QSoftCore *core=CORELIB::QSoftCore::getCore();

    QAction *ac;
    QList<QAction*> aclist;

    ac=new QAction(this);
    ac->setSeparator(true);
    aclist.append(ac);

    ac=core->action("LanguageManager-Add");
    if(ac!=NULL)
    {
        connect(ac,SIGNAL(triggered()),this,SLOT(addLanguage()));
        aclist.append(ac);
    }

    ac=core->action("LanguageManager-Del");
    if(ac!=NULL)
    {
        connect(ac,SIGNAL(triggered()),this,SLOT(delLanguage()));
        aclist.append(ac);
    }

    ac=new QAction(this);
    ac->setSeparator(true);
    aclist.append(ac);


    toolbar->addButtonActions(aclist);

    QLabel *label=new QLabel;
    label->setText(tr("Language Manager"));
    label->setStyleSheet("color:rgb(255,255,255);");
    toolbar->setLabelWidget(label);
    connect(m_languageList,SIGNAL(clicked(QModelIndex)),m_languageList,SLOT(edit(QModelIndex)));


    SHAREDLIB::QProjectCore *c=SHAREDLIB::QProjectCore::getCore();
    connect(c,SIGNAL(projectOpen()),this,SLOT(load()));
    connect(c,SIGNAL(projectClosed()),this,SLOT(clear()));

    QPalette p=m_languageList->palette();
    p.setColor(QPalette::Inactive,QPalette::Highlight,p.color(QPalette::Active,QPalette::Highlight));
    p.setColor(QPalette::Inactive,QPalette::HighlightedText,p.color(QPalette::Active,QPalette::HighlightedText));
    m_languageList->setPalette(p);

}

void QLanguageManagerView::addLanguage()
{
    QAddLanguageDialog dlg(this);
    dlg.exec();
    QString language=dlg.get_language();

    if(language!="")
    {
        emit need_make_page_position();
        QMap<QString,QVariant> param;
        param.insert("name",language);
        param.insert("index",m_items.keys().size());
        param.insert("page_position",m_page_position);
        tagPagePositionInfo info=m_page_position.value<tagPagePositionInfo>();
        info.m_data.insert("QLanguageManagerView::select",m_items.keys().size());
        QVariant v;
        v.setValue<tagPagePositionInfo>(info);
        param.insert("page_position",v);
        CORELIB::QAbstractUndoCommand *cmd=new CORELIB::QAbstractUndoCommand(param);
        connect(cmd->object(),SIGNAL(redo()),this,SLOT(cammand_add()));
        connect(cmd->object(),SIGNAL(undo()),this,SLOT(cammand_remove()));
        CORELIB::QSoftCore::getCore()->get_undo_stack()->push(cmd);
    }
}

void QLanguageManagerView::addLanguageItem(QObject *obj)
{
    if(obj==NULL)
    {
        return;
    }
    QTreeWidgetItem* item=new QTreeWidgetItem(m_languageList);
    m_items.insert(obj,item);
    item->setText(0,QString::number(m_languageList->indexOfTopLevelItem(item)+1));
    item->setText(1,obj->property("languageName").toString());
    item->setText(2,obj->property("explanation").toString());
    item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);

}

void QLanguageManagerView::insertLanguageItem(int index, QObject *obj)
{
    if(obj==NULL)
    {
        return;
    }
    QTreeWidgetItem* item=new QTreeWidgetItem(NULL);
    m_languageList->insertTopLevelItem(index,item);
    m_items.insert(obj,item);
    item->setText(0,QString::number(m_languageList->indexOfTopLevelItem(item)+1));
    item->setText(1,obj->property("languageName").toString());
    item->setText(2,obj->property("explanation").toString());
    item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
}

void QLanguageManagerView::delLanguage()
{
    QMapIterator<QObject*,QTreeWidgetItem*> it(m_items);
    while(it.hasNext())
    {
        it.next();
        if(it.value()->isSelected())
        {
            QMap<QString,QVariant> param;
            emit need_make_page_position();
            param.insert("name",it.key()->property("languageName"));
            param.insert("index",m_languageList->indexOfTopLevelItem(it.value()));
            param.insert("explanation",it.key()->property("explanation"));
            param.insert("page_position",m_page_position);
            tagPagePositionInfo info=m_page_position.value<tagPagePositionInfo>();
            info.m_data.insert("QLanguageManagerView::select",m_languageList->indexOfTopLevelItem(it.value()));
            QVariant v;
            v.setValue<tagPagePositionInfo>(info);
            param.insert("page_position",v);
            SHAREDLIB::QLanguageManager *lm=SHAREDLIB::QProjectCore::getCore()->languageManager();

            QObject* obj=lm->getLanguage(it.key()->property("languageName").toString());

            int count=lm->getItemCount();
            QStringList trans;
            SHAREDLIB::tagLanguageItem *item;
            for(int i=0;i<count;i++)
            {
                item=lm->getTextItem(i);
                trans.append(item->m_id+"="+item->m_translate.value(obj));
            }
            param.insert("item",trans);


            CORELIB::QAbstractUndoCommand *cmd=new CORELIB::QAbstractUndoCommand(param);
            connect(cmd->object(),SIGNAL(redo()),this,SLOT(cammand_remove()));
            connect(cmd->object(),SIGNAL(undo()),this,SLOT(cammand_add()));

            CORELIB::QSoftCore::getCore()->get_undo_stack()->push(cmd);
            return;
        }
    }
}

void QLanguageManagerView::updateNo()
{
    QMapIterator<QObject*,QTreeWidgetItem*> it(m_items);
    while(it.hasNext())
    {
        it.next();
        it.value()->setText(0,QString::number(m_languageList->indexOfTopLevelItem(it.value())+1));
    }
}

void QLanguageManagerView::itemUp()
{
    QMapIterator<QObject*,QTreeWidgetItem*> it(m_items);
    while(it.hasNext())
    {
        it.next();
        if(it.value()->isSelected())
        {
            SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();
            int index=m_languageList->indexOfTopLevelItem(it.value());
            if(index>0)
            {
                core->languageManager()->swapLanguage(index,index-1);
                m_languageList->takeTopLevelItem(index);
                m_languageList->insertTopLevelItem(index-1,it.value());
                m_languageList->clearSelection();
                it.value()->setSelected(true);
                updateNo();
            }
            return;
        }
    }
}

void QLanguageManagerView::itemDown()
{
    QMapIterator<QObject*,QTreeWidgetItem*> it(m_items);
    while(it.hasNext())
    {
        it.next();
        if(it.value()->isSelected())
        {
            SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();
            int index=m_languageList->indexOfTopLevelItem(it.value());
            if(index>=0 && index<m_items.size()-1)
            {
                core->languageManager()->swapLanguage(index,index+1);
                m_languageList->takeTopLevelItem(index);
                m_languageList->insertTopLevelItem(index+1,it.value());
                m_languageList->clearSelection();
                it.value()->setSelected(true);
                updateNo();
            }
            return;
        }
    }
}

void QLanguageManagerView::load()
{
    SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();
    SHAREDLIB::QLanguageManager *manager=core->languageManager();

    int count=manager->languageCount();
    for(int i=0;i<count;i++)
    {
        addLanguageItem(manager->getLanguage(i));
    }
    if(count>0)
    {
        m_languageList->setCurrentIndex(m_languageList->model()->index(0,0));
    }
}

void QLanguageManagerView::clear()
{
    m_items.clear();
    m_languageList->clear();
}

void QLanguageManagerView::cammand_add()
{
    QString name=sender()->property("name").toString();
    QString ex=sender()->property("explanation").toString();
    int index=sender()->property("index").toInt();
    QStringList l=sender()->property("item").toStringList();
    SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();

    QObject* obj=core->languageManager()->getLanguage(name);
    if(obj!=NULL)
    {
        return;
    }

    obj=new QObject();
    obj->setProperty("languageName",name);
    obj->setProperty("explanation",ex);
    core->languageManager()->insertLanguage(index,obj);
    foreach(QString str,l)
    {
        int index=str.indexOf("=");
        QString id=str.left(index);
        QString text=str.mid(index+1);
        core->languageManager()->setText(name,id,text);
    }

    core->languageManager()->refreshLanguage();
    insertLanguageItem(index,obj);
    m_languageList->setCurrentItem(m_items.value(obj));
    updateNo();
}

void QLanguageManagerView::cammand_remove()
{
    QString name=sender()->property("name").toString();

    SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();
    QObject* obj=core->languageManager()->getLanguage(name);
    if(obj!=NULL)
    {
        QTreeWidgetItem* item=m_items.value(obj);
        if(item!=NULL)
        {
            delete item;
        }
        m_items.remove(obj);
    }
    core->languageManager()->removeLanguage(name);
    core->languageManager()->refreshLanguage();
    updateNo();
}

void QLanguageManagerView::cammand_rename()
{
    SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();
    QString old=sender()->property("old_name").toString();
    QString now=sender()->property("new_name").toString();
    QObject* obj=core->languageManager()->getLanguage(old);
    core->languageManager()->setLanguageName(obj,now);
    QTreeWidgetItem* item=m_items.value(obj);
    item->setText(1,now);
    m_languageList->setCurrentItem(item);
    sender()->setProperty("old_name",now);
    sender()->setProperty("new_name",old);
}

void QLanguageManagerView::cammand_property()
{
    SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();
    QString old=sender()->property("old_value").toString();
    QString now=sender()->property("new_value").toString();
    QString language=sender()->property("language").toString();
    QObject* obj=core->languageManager()->getLanguage(language);
    obj->setProperty("explanation",now);
    QTreeWidgetItem* item=m_items.value(obj);
    item->setText(2,now);
    m_languageList->setCurrentItem(item);
    sender()->setProperty("old_value",now);
    sender()->setProperty("new_value",old);
}

void QLanguageManagerView::set_page_position(const QVariant &info)
{
    m_page_position=info;
}

void QLanguageManagerView::make_page_position(QVariant &info)
{
}

bool QLanguageManagerView::pagePosition(const QVariant &param)
{
    tagPagePositionInfo in=param.value<tagPagePositionInfo>();
    int index=in.m_data.value("QLanguageManagerView::select").toInt();
    if(index<m_items.values().size())
    {
        m_languageList->setCurrentIndex(m_languageList->model()->index(index,0));
    }
    return false;
}

bool QLanguageManagerView::eventFilter(QObject *o, QEvent *e)
{
    if(o==m_languageList)
    {
        if(e->type()==QEvent::KeyPress)
        {
            QKeyEvent *event=(QKeyEvent*)e;
            if(event->key()==Qt::Key_Delete)
            {
                delLanguage();
                return true;
            }
        }
    }
    return false;
}
